package 多线程.Threadpool;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;



public class MyLock implements Lock {
    /**
     * 原理上,外部类在高并发的时候需要锁,就会new一个MyLock对象;
     */
    private MySync mySync = new MySync();

    /**
     * 锁上之后不可打断,阻塞会进入entrySet;
     */
    @Override
    public void lock() {
        mySync.acquire(1);
    }

    /**
     * 同步器打断方法;
     * @throws InterruptedException
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
        mySync.acquireInterruptibly(1);
    }

    /**
     * 只会尝试一次获取锁;
     */
    @Override
    public boolean tryLock() {
        return mySync.tryAcquire(1);
    }

    /**
     * 同步器尝试上锁方法
     * @param time
     * @param unit
     * @return
     * @throws InterruptedException
     */
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return mySync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        mySync.tryRelease(1);
    }

    @Override
    public Condition newCondition() {
        return mySync.newCondition();
    }


    //不可重入锁->独占锁;
    public class MySync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (super.compareAndSetState(0, 1)){    //加锁成功;
                super.setExclusiveOwnerThread(Thread.currentThread());  //把主人线程的地址改成本线程;
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            super.setExclusiveOwnerThread(null);
            super.setState(0);  //OwnerThread没有volatile修饰,所以得放volatile变量前面保证其他线程可见;
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            return super.getState() == 1;   //为1就持有独占锁;
        }

        public Condition newCondition(){
            return new ConditionObject();   //内部类;
        }
    }

}
